package com.ssl.security.util;

import com.ssl.security.constants.CertFactoryTypeEnum;
import com.ssl.security.exception.SecurityException;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.Provider;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;

/**
 * 描述：证书操作工具类
 *
 * @author ssl
 * @create 2021/3/19 0019.
 */
public class CertificateUtils {
    public static final String PEM_PREFIX = "-----BEGIN CERTIFICATE-----";
    public static final String PEM_SUFFIX = "-----END CERTIFICATE-----";


    private static Provider BC_PROVIDER = new BouncyCastleProvider();


    /**
     * 获取X509证书
     *
     * @param certEncodedBase64 证书Base64（如果包含头尾和换行格式，会自动去除）
     * @return
     */
    public static X509Certificate loadCert(String certEncodedBase64) throws SecurityException {
        // 去除头尾和换行格式
        certEncodedBase64 = removeComments(certEncodedBase64);
        byte[] certEncoded = Base64.decodeBase64(certEncodedBase64);
        return loadCert(certEncoded);
    }

    /**
     * 根据证书二进制流获取X509证书
     *
     * @param certEncoded 证书二进制流
     * @return
     */
    public static X509Certificate loadCert(byte[] certEncoded) throws SecurityException {
        InputStream inputStream = new ByteArrayInputStream(certEncoded);
        return loadCert(inputStream, BC_PROVIDER);
    }


    /**
     * 获取证书对象
     *
     * @param inputStream 证书输入流
     * @return
     * @throws SecurityException
     */
    private static X509Certificate loadCert(InputStream inputStream, Provider provider) throws SecurityException {
        X509Certificate x509Certificate;
        CertificateFactory certificateFactory;
        try {
            certificateFactory = CertificateFactory.getInstance(CertFactoryTypeEnum.x509.getValue(), provider);
            x509Certificate = (X509Certificate) certificateFactory.generateCertificate(inputStream);
        } catch (CertificateException e) {
            throw new SecurityException("转换证书失败。", e);
        } finally {
            if (null != inputStream) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                }
            }
        }
        return x509Certificate;
    }

    /**
     * 删除 X.509 PEM 格式头与尾
     *
     * @param pem
     * @return
     */
    private static String removeComments(String pem) {
        pem = StringUtils.remove(pem, PEM_PREFIX);
        pem = StringUtils.remove(pem, PEM_SUFFIX);
        pem = pem.replaceAll("\\s", "");
        return pem;
    }

}
